//package com.mark.plugins;
//
//import java.lang.reflect.Field;
//import java.sql.Connection;
//import java.sql.PreparedStatement;
//import java.sql.ResultSet;
//import java.sql.SQLException;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
//import org.apache.ibatis.executor.ErrorContext;
//import org.apache.ibatis.executor.ExecutorException;
//import org.apache.ibatis.executor.statement.BaseStatementHandler;
//import org.apache.ibatis.executor.statement.RoutingStatementHandler;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.ParameterMapping;
//import org.apache.ibatis.mapping.ParameterMode;
//import org.apache.ibatis.plugin.Invocation;
//import org.apache.ibatis.reflection.MetaObject;
//import org.apache.ibatis.reflection.property.PropertyTokenizer;
//import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
//import org.apache.ibatis.session.Configuration;
//import org.apache.ibatis.type.TypeHandler;
//import org.apache.ibatis.type.TypeHandlerRegistry;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import com.mark.util.ReflectUtil;
//
//public class PagePlugin implements IPlugin {
//
//	Logger logger = LoggerFactory.getLogger(this.getClass());
//
//	private Map<String, String> propertyMap = new HashMap<String, String>();
//	private String dialect = null;
//
//	@Override
//	public void init(String propertyParameter) throws Exception {
//		if (propertyParameter == null)
//			throw new ExecutorException("plugin [PagePlugin] --> paramter dialect is null!");
//		String[] pms = propertyParameter.split(";");
//		for (String str : pms) {
//			str = str.trim();
//			if (str.length() == 0)
//				continue;
//			String[] kv = str.split("=");
//			if (kv.length == 0)
//				continue;
//			propertyMap.put(kv[0], kv[1]);
//		}
//		dialect = propertyMap.get("dialect");
//		if (dialect == null)
//			throw new ExecutorException("plugin [PagePlugin] --> paramter dialect is null!");
//	}
//
//	@Override
//	public Object intercept(Invocation ivk) throws Exception {
//		Object target = ivk.getTarget();
//		if (!"prepare".equals(ivk.getMethod().getName()) || !(target instanceof RoutingStatementHandler)) {
//			return ivk.proceed();
//		}
//		RoutingStatementHandler statementHandler = (RoutingStatementHandler) target;
//		BaseStatementHandler delegate = (BaseStatementHandler) ReflectUtil.getValueByFieldName(statementHandler, "delegate");
//		MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getValueByFieldName(delegate, "mappedStatement");
//
//		BoundSql boundSql = delegate.getBoundSql();
//		Object parameterObject = boundSql.getParameterObject();
//		if (parameterObject == null) {
//			throw new NullPointerException("parameterObject");
//		}
//		Connection connection = (Connection) ivk.getArgs()[0];
//		String sql = boundSql.getSql();
//		String countSql = "select count(0) from (" + sql + ") as a_";
//		logger.debug("分页总数sql:" + countSql);
//		PreparedStatement countStmt = connection.prepareStatement(countSql);
//		BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
//		setParameters(countStmt, mappedStatement, countBS, parameterObject);
//		ResultSet rs = countStmt.executeQuery();
//		int count = 0;
//		if (rs.next()) {
//			count = rs.getInt(1);
//		}
//		rs.close();
//		countStmt.close();
//
//		String pageSql = null;
//		if (parameterObject instanceof PageComponent) {
//			// 以VO形式传参数
//			PageComponent<Object> page = null;
//			page = (PageComponent) parameterObject;
//			page.setRecordCount(count);
//			pageSql = generatePageSql(sql, page);
//		} else if (parameterObject instanceof Map) {
//			// 以map形式传参，
//			Map<String, Object> map = (Map<String, Object>) parameterObject;
//			if (map == null)
//				map = new HashMap<String, Object>();
//			map.put("recordCount", count);
//			pageSql = generatePageSqlMap(sql, map);
//		} else {
//			PageComponent page = null;
//			Field pageField = ReflectUtil.getFieldByFieldName(parameterObject, "pageIndex");
//			if (pageField != null) {
//				page = (PageComponent) ReflectUtil.getValueByFieldName(parameterObject, "pageIndex");
//				if (page == null)
//					page = new PageComponent();
//				page.setRecordCount(count);
//				ReflectUtil.setValueByFieldName(parameterObject, "pageIndex", page);
//			} else {
//				throw new NoSuchFieldException(parameterObject.getClass().getName());
//			}
//			pageSql = generatePageSql(sql, page);
//		}
//		logger.debug("分页sql:" + pageSql);
//		ReflectUtil.setValueByFieldName(boundSql, "sql", pageSql);
//		return ivk.proceed();
//	}
//
//	private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
//		ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
//		List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//		if (parameterMappings != null) {
//			Configuration configuration = mappedStatement.getConfiguration();
//			TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
//			MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
//			for (int i = 0; i < parameterMappings.size(); i++) {
//				ParameterMapping parameterMapping = parameterMappings.get(i);
//				if (parameterMapping.getMode() != ParameterMode.OUT) {
//					Object value;
//					String propertyName = parameterMapping.getProperty();
//					PropertyTokenizer prop = new PropertyTokenizer(propertyName);
//					if (parameterObject == null) {
//						value = null;
//					} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//						value = parameterObject;
//					} else if (boundSql.hasAdditionalParameter(propertyName)) {
//						value = boundSql.getAdditionalParameter(propertyName);
//					} else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) {
//						value = boundSql.getAdditionalParameter(prop.getName());
//						if (value != null) {
//							value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
//						}
//					} else {
//						value = metaObject == null ? null : metaObject.getValue(propertyName);
//					}
//					TypeHandler typeHandler = parameterMapping.getTypeHandler();
//					if (typeHandler == null) {
//						throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
//					}
//					typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
//				}
//			}
//		}
//	}
//
//	private String generatePageSql(String sql, PageComponent page) {
//		if (page != null ) {
//			StringBuffer pageSql = new StringBuffer();
//			if ("mysql".equals(dialect)) {
//				pageSql.append(sql);
//				pageSql.append(" limit " + (page.getPageIndex()<=0?0:page.getPageIndex()) + "," + page.getPageSize());
//			} else if ("oracle".equals(dialect)) {
//				pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
//				pageSql.append(sql);
//				pageSql.append(")  tmp_tb where ROWNUM<=");
//				pageSql.append(page.getPageIndex() + page.getPageSize());
//				pageSql.append(") where row_id>");
//				pageSql.append(page.getPageIndex());
//			}else{
//				throw new RuntimeException("不支持的数据库类型! [dialect="+dialect+"]");
//			}
//			return pageSql.toString();
//		} else {
//			return sql;
//		}
//	}
//
//	private String generatePageSqlMap(String sql, Map<String, Object> map) {
//		if (map != null) {
//			StringBuffer pageSql = new StringBuffer();
//			if ("mysql".equals(dialect)) {
//				pageSql.append(sql);
//
//				// 根据索引计算分页
//				Integer startLimit = Integer.parseInt(map.get("pageIndex").toString()) * Integer.parseInt(map.get("pageSize").toString());
//				pageSql.append(" limit " + (startLimit<=0?0:startLimit) + "," + map.get("pageSize"));
//
//			} else if ("oracle".equals(dialect)) {
//				pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
//				pageSql.append(sql);
//				pageSql.append(")  tmp_tb where ROWNUM<=");
//				pageSql.append(map.get("pageIndex").toString() + map.get("pageSize"));
//				pageSql.append(") where row_id>");
//				pageSql.append(map.get("pageIndex"));
//			}else{
//				throw new RuntimeException("不支持的数据库类型! [dialect="+dialect+"]");
//			}
//			return pageSql.toString();
//		} else {
//			return sql;
//		}
//	}
//}
